﻿#include"XQFtp.hpp"
#include"curl/curl.h"
#include"XQCoding.h"
#include<QFile>
#include<QStack>
#include<QTextStream>
XQFtp::XQFtp(QObject* parent)
    :QObject(parent)
{
  
}

XQFtp::~XQFtp()
{

}

void XQFtp::setHost(const QString& host, const unsigned short int port)
{
	m_ftpInfo.setHost(host);
	m_ftpInfo.setPort(port);

}

XQFtp* XQFtp::copy(QObject* parent)
{
    auto ftp = new XQFtp(parent);
    ftp->m_ftpInfo = m_ftpInfo;
    ftp->m_local_file_path = m_local_file_path;
    ftp->m_remote_file_dir = m_remote_file_dir;
    ftp->m_remote_file_path = m_remote_file_path;
    ftp->m_timeout = m_timeout;
    return ftp;
}

void XQFtp::login(const QString& username, const QString& password)
{
	m_ftpInfo.setUserName(username);
	m_ftpInfo.setPassword(password);
}
void XQFtp::setRemoteFileDir(const QString& dir)
{
    m_remote_file_dir = dir;
    m_remote_file_dir.replace('\\','/');
    if (m_remote_file_dir.back() != '/')
        m_remote_file_dir.push_back('/');
   
}
void XQFtp::cd(const QString& dir)
{
    m_remote_file_dir += dir;
    if (dir.back() != '/')
        m_remote_file_dir.push_back('/');
}

int XQFtp::mkdir(const QString& path)
{
   return slotFTPCMDExec(QString("MKD %1").arg(path));
}

int XQFtp::mkpath(const QString& path)
{
    if (path.isEmpty())
    {
        return -1;
    }
    
    QString Path = path;
    Path.replace('\\','/');//替换
    int nSel = Path.indexOf('/', 1);
    while (nSel!=-1)
    {
        mkdir(Path.left(nSel));
        nSel = Path.indexOf('/', nSel+1);
    }
    mkdir(Path);
    return CURLE_OK;
}

int XQFtp::remove(const QString& path)
{
    return slotFTPCMDExec(QString("DELE %1").arg(path));
}

int XQFtp::removeDir(const QString& path)
{
    QStack<QString> stackDir;
    QStack<QString> stack;
    stackDir.push(path);
    //遍历获取全部文件和目录
    while (!stackDir.isEmpty())
    {
        QString path = stackDir.top();
        stack.push(path);
        stackDir.pop();
        auto infos = fileList(path);
        for (auto&info:infos)
        {
            QString curPath = path + "/"+info.name();
            if (info.type() == FileType::dir)
            {
                curPath += "/";
                stackDir.push(curPath);
            }
            stack.push(curPath);
        }
    }
    //开始遍历删除全部
    size_t count = 0;
    while (!stack.isEmpty())
    {
        QString path = stack.top();
        remove(path);
        stack.pop();
        ++count;
    }
    return count;
}

int XQFtp::rename(const QString& path, const QString& newName)
{
    return slotFTPCMDExec(QString("RNFR %1RNTO %2").arg(path).arg(newName));
}

void XQFtp::setPath(const QString& local_file_path, const QString& remote_file_path)
{
    m_local_file_path = local_file_path;
    m_remote_file_path = remote_file_path;
}

CURL* XQFtp::init()
{
    CURL* curl= curl_easy_init();
    if (curl)
    {
        /*用户名和密码*/
        curl_easy_setopt(curl, CURLOPT_USERNAME, m_ftpInfo.userName().toLocal8Bit().data());
        curl_easy_setopt(curl, CURLOPT_PASSWORD, m_ftpInfo.password().toLocal8Bit().data());
        
        //curl_easy_setopt(m_curl, CURLOPT_NOBODY, 1);
       
        //超时
        if (m_timeout)
            curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, m_timeout);
    }
    return curl;
}

QString XQFtp::setUrl(QString path, const bool updataPath)
{
    //设置url
    QString url = m_ftpInfo.url();
    path.replace('\\', '/');
    if (path.isEmpty() || path[0] != '/')
    {
        url += m_remote_file_dir;
    }
    url += path;
    if (updataPath)
    {
        m_remote_file_dir = path;
    }
    return std::move(url);
}

int XQFtp::slotFTPCMDExec(const QString& CMD, const QString& path , const bool updataPath )
{
    curl_global_init(CURL_GLOBAL_ALL);
    struct curl_slist* CMDlist = nullptr;//初始化命令列表
    auto curl=init();
    //设置url
    QString url = setUrl(path, updataPath);
    curl_easy_setopt(curl, CURLOPT_URL, url.toLocal8Bit().data());

    if (CMDlist != nullptr)
    {
        curl_slist_free_all(CMDlist);//清空命令列表 - 此函数没有返回值
        CMDlist = nullptr;//清空后 一定要手动赋值NULL
    }
    curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
    if (CMD.indexOf("RNTO") != 0)
    {
        CMDlist = curl_slist_append(CMDlist, CMD.mid(0, CMD.indexOf("RNTO")).toLocal8Bit().data());//!!!!在FTP的时候，这个一定只能隔一个空格 所有命令都是这样 而且不用加那么长的路径
        CMDlist = curl_slist_append(CMDlist, CMD.mid(CMD.indexOf("RNTO")).toLocal8Bit().data());
    }
    else
    {
        CMDlist = curl_slist_append(CMDlist, CMD.toLocal8Bit().data());
    }
    curl_easy_setopt(curl, CURLOPT_POSTQUOTE, CMDlist);// CURLOPT_POSTQUOTE CURLOPT_QUOTE 我的理解出了执行的优先级不一样 其他没区别
    auto res = curl_easy_perform(curl);//执行完这个之后 就一定会打印文件列表 ！！ 即使你把文件列表回调函数指针赋值为null 也不行！！
    return res;
}
